package com.kova.api.controller;

import com.kova.api.cipher.DecryptRequest;
import com.kova.api.cipher.EncryptResponse;
import com.kova.api.common.Result;
import com.kova.api.common.ResultEnum;
import com.kova.api.crypto.Crypto;
import com.kova.api.limit.RequestLimit;
import com.kova.api.log.annotation.ApiLog;
import com.kova.api.log.common.ApiLogConst;
import com.kova.api.token.AccessToken;
import com.kova.api.verify.ParamVerifier;
import com.kova.api.verify.ParamsVerify;
import com.kova.api.version.ApiVersion;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/api/{version}/user")
@Tag(name = "示例接口", description = "示例相关的 API 接口")
public class UserController {


    /**
     *    注解的相关使用
     *
     *    @ApiVersion(1)             表示接口版本控制，如 @ApiVersion(1) 表示：v1，@ApiVersion(2) 表示：v2
     *    @DecryptRequest            表示请求的body是密文，需要解密
     *    @DecryptRequest(false)     表示请求的body是明文，不需要解密
     *    @EncryptResponse           表示响应给客户端，返回内容是密文
     *    @EncryptResponse(false)    表示响应给客户端，返回内容是明文
     *    @AccessToken               表示请求头验证token
     *    @AccessToken(false)        表示请求头不验证token
     *    @RequestLimit              表示接口调用频率限制，默认为5000毫秒
     *    @ParamsVerify              表示验证方法的【共有参数】(注： 在om.kova.api.verify.AopParameterVerify类中找到validateRequestParams方法，修改成自已的参数验证)
     *    @ParamsVerify(true)        表示验证方法的【共有参数 + 登录后的token参数】 (注： 在om.kova.api.verify.AopParameterVerify类中找到validateRequestParams方法，修改成自已的参数验证)
     *
     *    【共有参数】                 表示每个接口方法都要带的参数，如：oncestr，timestamp，sign，不需要则方法不用注解 @ParamsVerify
     *
     *    注：@ParamsVerify 注解需要在 @DecryptRequest之后，需先解密在验证参数，如下所示:
     *
     *    @DecryptRequest
     *    @ParamsVerify
     *
     *
     *
     */

    /**
     *  Swagger生成API文档
     *
     * Springdoc：http://localhost:8080/swagger-ui.html 或 http://localhost:8080/swagger-ui/index.html
     *
     *
     */



    @Autowired
    @Qualifier("rrCrypto")
    private Crypto crypto;


    /**
     *   token验证
     *   curl http://localhost:8080/api/v1/user/verifyToken -X POST  -H "Content-Type:application/json" -H "token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyTmFtZSI6Imtpbmdib3lyYW5nIiwiZXhwIjoxNzYxNTcxMTY0LCJ1c2VySWQiOiIxIn0.Injq0CXaSh3xbuCtRr6-PlWvWNwggs2znU_eczQlt0s"  -d '{"name":"kingboyrang"}'
     *
     * @param params
     * @return
     */
    @ResponseBody
    @ApiVersion(1)  //接口版本
    @AccessToken  //token验证
    @RequestMapping(value = "/verifyToken", method = RequestMethod.POST)
    @Operation(summary = "token验证", description = "token验证测试")
    public Result getVerifyTokenInfo(@RequestBody Map<String,Object> params){
        return Result.ok();
    }


    /**
     * 接口频率访问测试
     *
     * 非加密测试: curl http://localhost:8080/api/v1/user/limit -X POST  -H "Content-Type:application/json" -d '{"name":"kingboyrang"}'
     * 加密测试: curl http://localhost:8080/api/v1/user/limit -X POST  -d '7i+9ZDZD8AGHoVwCMJyDzoVZOP9rXOhOIOdphcJvI+cpdXDqFSwbzoIudYlnWXjJ'
     *
     * @return
     */
    @ResponseBody
    @ApiVersion(1)  //接口版本
    @RequestMapping(value = "/limit", method = RequestMethod.POST)
    @RequestLimit //接口频率访问时间设置，默认值为5000
    //@RequestLimit(time = 1000) //接口频率访问时间设置
    @DecryptRequest  //请求解密
    @ApiLog(module = ApiLogConst.detail,type = ApiLogConst.detailType,desc = ApiLogConst.detailDesc) //日志记录
    @Operation(summary = "接口频率访问", description = "接口频率访问测试接口")
    public Result getReuqestLimitInfo(@RequestBody String body){
        Map<String, Object> resultParams = new HashMap<String, Object>();
        resultParams.put("info", "接口访问限制测试");
        return Result.ok(resultParams);
    }


    @ResponseBody
    @ApiVersion(1)  //接口版本
    @AccessToken
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    @DecryptRequest  //请求解密
    @EncryptResponse //响应加密
    //@ParamsVerify   //公有参数验证
    @ApiLog(module = ApiLogConst.detail,type = ApiLogConst.detailType,desc = ApiLogConst.detailDesc) //日志记录
    public Result getUserDetail(@RequestBody  Map<String,Object> params){ //@RequestBody Map<String,Object> params 或者 @RequestBody String body


        //方法其它参数验证
        ParamVerifier<Object, String> verifier = new ParamVerifier<>();
        Optional<String> finish = verifier
                .verify(params.get("uid"), t -> t!=null&&!ObjectUtils.isEmpty(t),"参数uid不为空")
                .verify(params.get("key"), t -> t!=null&&!ObjectUtils.isEmpty(t),"参数key不为空")
                .verify(params.get("newsId"), t -> t!=null&&!ObjectUtils.isEmpty(t),"参数newsId不为空")
                .finish();
        if(finish.isPresent()) {
            String s = finish.get();
            return Result.builder().code(ResultEnum.PARAM_ERROR.getCode()).msg(s).build();
        }

        //log.info("解密后的body={}",body);
        Map<String, Object> resultParams = new HashMap<String, Object>();
        resultParams.put("name", "kingboyrang");
        resultParams.put("id", "1");
        resultParams.put("phone", "13621541236");
        resultParams.put("sex", "男");
        return Result.ok(resultParams);

    }

    /**
     * 用户登录(请求与响应需要加解密)
     *
     * 测试: curl http://localhost:8080/api/v1/user/login -X POST  -d '7i+9ZDZD8AGHoVwCMJyDzoVZOP9rXOhOIOdphcJvI+cpdXDqFSwbzoIudYlnWXjJ'
     *
     * @param body
     * @return
     */
    @ResponseBody
    @ApiVersion(1)  //接口版本
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @DecryptRequest  //请求解密
    @EncryptResponse //响应加密
    @ApiLog(module = ApiLogConst.login,type = ApiLogConst.loginType,desc = ApiLogConst.loginDesc)
    public Result userLogin(@RequestBody String body){

        log.info("解密后的body={}",body);

        Map<String, Object> resultParams = new HashMap<String, Object>();
        resultParams.put("name", "kingboyrang");
        resultParams.put("id", "1");
        resultParams.put("phone", "13621541236");
        return Result.ok(resultParams);
    }

    /**
     * 获取用户信息(请求响应需要加解密)
     *
     * 测试: curl http://localhost:8080/api/v1/user/info -X POST -H "Content-Type:application/json" -d '{"userName":"kingboyrang","password"}'
     *
     * @param body
     * @return
     */
    @ResponseBody
    @ApiVersion(1)  //接口版本
    @RequestMapping(value = "/info", method = RequestMethod.POST)
    @DecryptRequest(false)  //请求不需要解密
    @EncryptResponse //响应加密(响应不加密，可设置为@EncryptResponse(false))
    @ApiLog(module = ApiLogConst.info,type = ApiLogConst.infoType,desc = ApiLogConst.infoDesc) //日志记录
    public Result userInfo(@RequestBody String body){

        log.info("未加密body={}",body);
        String jsonStr = crypto.encrypt(body);
        log.info("加密后的body = {}",jsonStr);

        Map<String, Object> resultParams = new HashMap<String, Object>();
        resultParams.put("name", "kingboyrang");
        resultParams.put("id", "1");
        resultParams.put("phone", "13621541236");
        return Result.ok(resultParams);
    }


    /**
     *  测试接口   http://localhost:8080/api/v1/user/test?name=wlz&age=20
     * @param name
     * @param age
     * @return
     */
    @ResponseBody
    @ApiVersion(1)  //接口版本
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    @ApiLog(module = ApiLogConst.test,type = ApiLogConst.testType,desc = ApiLogConst.testDesc) //日志记录
    public Result userTestMehotd(@RequestParam(required = true,value = "name") String name,@RequestParam(required = true,value = "age") String age){

       log.info("name={},age={}",name,age);

        Map<String, Object> resultParams = new HashMap<String, Object>();
        resultParams.put("name", name);
        resultParams.put("id", "1");
        resultParams.put("phone", "13621541236");
        return Result.ok(resultParams);
    }
}
